package find_way;

import path_finding.AStar;
import path_finding.Heuristic;
import path_finding.PathFinding;
import path_finding.XyTrans;

import javax.swing.*;
import javax.swing.Timer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;

class DijkstraShow extends JPanel implements ActionListener {
    private static final int GRID_SIZE = 100; // 100x100 网格
    private static final int CELL_SIZE = 10;   // 每个单元格的大小（像素）
    private static final int PADDING = 20;    // 边距
    private int current;
    private int target;
    private Timer timer;
    private Set<Integer> obstacleSet = new HashSet<>();
    private List<Integer> findWay = new LinkedList<>();
    private Iterator<Integer> pathIterator;
    private int[][]visited;
    private List<Integer> drawWay = new LinkedList<>();

    DijkstraShow() {
        timer = new Timer(50, this);
        obstacleSet.add(202);    // 起始障碍物
        obstacleSet.add(203);
        obstacleSet.add(215);
        obstacleSet.add(225);
        obstacleSet.add(234);
        obstacleSet.add(245);

        for (int i = 10; i < 90; i += 2) {
            obstacleSet.add(i * 100 + 30);  // 垂直障碍墙
        }

        for (int i = 15; i < 85; i += 3) {
            obstacleSet.add(i * 100 + 45 + (i % 2) * 10);
        }

        int[] roomCenters = {3030, 5050, 7070, 3060, 6080};
        for (int center : roomCenters) {
            int x = center / 100;
            int y = center % 100;
            for (int i = -5; i <= 5; i++) {
                for (int j = -5; j <= 5; j++) {
                    if (Math.abs(i) == 5 || Math.abs(j) == 5) {
                        obstacleSet.add((x + i) * 100 + (y + j));
                    }
                }
            }
            obstacleSet.remove((x + 5) * 100 + y);
            obstacleSet.remove((x - 5) * 100 + y);
        }

        for (int i = 20; i < 80; i++) {
            obstacleSet.add(4000 + i);  // 水平长墙
            obstacleSet.add(i * 100 + 60);  // 垂直长墙
        }

        obstacleSet.add(1515);
        obstacleSet.add(2525);
        obstacleSet.add(3535);
        obstacleSet.add(4545);
        obstacleSet.add(5555);
        obstacleSet.add(6565);
        obstacleSet.add(7575);
        obstacleSet.add(8585);

        current = 1111;    // 起点 (11,11)
        target = 8888;      // 终点 (88,88)

        obstacleSet.remove(current);
        obstacleSet.remove(target);

        /*
        current = 11;
        target = 77;
        obstacleSet.add(10);
        obstacleSet.add(12);
        obstacleSet.add(21);
        obstacleSet.add(23);
        obstacleSet.add(14);
        obstacleSet.add(41);
        obstacleSet.add(42);
        obstacleSet.add(43);
        obstacleSet.add(44);
        obstacleSet.add(45);
        obstacleSet.add(46);
        obstacleSet.add(47);
        obstacleSet.add(48);
        obstacleSet.add(49);
        obstacleSet.add(65);
        obstacleSet.add(66);
        obstacleSet.add(67);
        obstacleSet.add(68);
        obstacleSet.add(75);
        obstacleSet.add(85);
        obstacleSet.add(78);
        obstacleSet.add(88);
        obstacleSet.add(94);
         */

        runAStar();
        timer.start();
    }

    private void runAStar() {
        PathFinding pathFinding = new AStar();
        //启发函数为0则是Dijkstra
        pathFinding.setHeuristic((fromX, fromY, toX, toY) -> 0);
        pathFinding.setXyTrans(new XyTrans() {
            @Override
            public int toId(int x, int y) {
                return x + y * GRID_SIZE;
            }

            @Override
            public int[] toXy(int id) {
                int []xy = new int[2];
                xy[0] = id % GRID_SIZE;
                xy[1] = id / GRID_SIZE;
                return xy;
            }
        });
        int grid[][] = new int[GRID_SIZE][GRID_SIZE];
        for (int obstacle : obstacleSet) {
            int x = obstacle % GRID_SIZE;
            int y = obstacle / GRID_SIZE;
            grid[x][y] = 1;
        }
        visited = new int[GRID_SIZE][GRID_SIZE];
        findWay = pathFinding.findPath(grid, current % GRID_SIZE, current / GRID_SIZE,
                target % GRID_SIZE, target / GRID_SIZE, visited);
        System.out.println("AStar 找到最优路径长度" + findWay.size());
        pathIterator = findWay.iterator();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        // 设置背景色
        setBackground(Color.WHITE);

        // 设置网格线颜色
        g.setColor(Color.LIGHT_GRAY);

        // 绘制水平线
        for (int i = 0; i <= GRID_SIZE; i++) {
            int y = PADDING + i * CELL_SIZE;
            g.drawLine(PADDING, y, PADDING + GRID_SIZE * CELL_SIZE, y);
        }

        // 绘制垂直线
        for (int i = 0; i <= GRID_SIZE; i++) {
            int x = PADDING + i * CELL_SIZE;
            g.drawLine(x, PADDING, x, PADDING + GRID_SIZE * CELL_SIZE);
        }

        // 绘制访问过的节点（浅蓝色）
        g.setColor(new Color(200, 230, 255));
        for (int i = 0; i < visited.length; ++ i) {
            for (int j = 0; j < visited[i].length; ++ j) {
                if (visited[i][j] != 1) continue;
                int x = PADDING + i * CELL_SIZE;
                int y = PADDING + j * CELL_SIZE;
                g.fillRect(x + 1, y + 1, CELL_SIZE - 1, CELL_SIZE - 1);
            }
        }

        // 填充选定的单元格为蓝色
        for (int current : drawWay) {
            g.setColor(Color.BLUE);
            int filledCellX = current % GRID_SIZE;
            int filledCellY = current / GRID_SIZE;
            int x = PADDING + filledCellX * CELL_SIZE;
            int y = PADDING + filledCellY * CELL_SIZE;
            g.fillRect(x + 1, y + 1, CELL_SIZE - 1, CELL_SIZE - 1);
        }

        g.setColor(Color.BLACK);
        for (int obstacle : obstacleSet) {
            int filledCellX = obstacle % GRID_SIZE;
            int filledCellY = obstacle / GRID_SIZE;
            int x = PADDING + filledCellX * CELL_SIZE;
            int y = PADDING + filledCellY * CELL_SIZE;
            g.fillRect(x + 1, y + 1, CELL_SIZE - 1, CELL_SIZE - 1);
        }

        g.setColor(Color.RED);
        int filledCellX = target % GRID_SIZE;
        int filledCellY = target / GRID_SIZE;
        int x = PADDING + filledCellX * CELL_SIZE;
        int y = PADDING + filledCellY * CELL_SIZE;
        g.fillRect(x + 1, y + 1, CELL_SIZE - 1, CELL_SIZE - 1);

        // 绘制网格信息
        g.setColor(Color.BLACK);
        g.drawString("100x100 Grid", PADDING, PADDING - 5);
        g.drawString("Total Cells: " + (GRID_SIZE * GRID_SIZE),
                PADDING, PADDING + GRID_SIZE * CELL_SIZE + 15);

    }

    @Override
    public Dimension getPreferredSize() {
        int size = PADDING * 2 + GRID_SIZE * CELL_SIZE;
        return new Dimension(size, size + 30);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (pathIterator != null && pathIterator.hasNext()) {
            current = pathIterator.next();
            drawWay.add(current);
            repaint();
        }
    }
}

public class DijkstraMain {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Dijkstra Show");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new DijkstraShow());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}
